package com.tian;

/**
 * {@code @description:} TODO
 *
 * @author tianwc 公众号：Java后端技术全栈
 * 在线刷题 1200+java面试题和1000+篇技术文章：<a href="https://woaijava.cc/">博客地址</a>
 * {@code @date:} 2024-05-10 10:55
 * {@code @version:} 1.0
 */
import org.redisson.Redisson;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.concurrent.atomic.AtomicLong;

public class UserRanking {
    public static final long MAX_INTEGER = Integer.MAX_VALUE;
    public static final double TIME_CONSTANT = Math.pow(10, -13);
    public static void main(String[] args) {
        // 创建Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);
        RScoredSortedSet<Long> ranking = redisson.getScoredSortedSet("user_ranking");
        ranking.delete();
        // 添加用户到排行榜
        addUserToRanking(redisson, 1001L, 100, LocalDateTime.now());
        addUserToRanking(redisson, 1002L, 200, LocalDateTime.now().minusDays(1));
        addUserToRanking(redisson, 1003L, 100, LocalDateTime.now().minusDays(1));
        addUserToRanking(redisson, 1004L, 100, LocalDateTime.now().plusMinutes(1));

        // 获取排行榜
        getRanking(redisson);

        // 关闭Redisson客户端
        redisson.shutdown();
    }

    private static void addUserToRanking(RedissonClient redisson, Long userId, int score, LocalDateTime achievedAt) {
        RScoredSortedSet<Long> ranking = redisson.getScoredSortedSet("user_ranking");
        double scoreWithTimestamp =calculateScore(score,achievedAt.toEpochSecond(ZoneOffset.UTC))  ;
        ranking.add(scoreWithTimestamp, userId);
    }
    public static double calculateScore(int contribution, long timestamp) {
        return contribution + (MAX_INTEGER - timestamp) * TIME_CONSTANT;
    }
    private static void getRanking(RedissonClient redisson) {
        RScoredSortedSet<Long> ranking = redisson.getScoredSortedSet("user_ranking");
        //
        AtomicLong rank = new AtomicLong(ranking.stream().count());
        ranking.entryRange(0, -1).forEach(entry -> {
            Double scoreWithTimestamp = entry.getScore();
            int score =  (scoreWithTimestamp.intValue());
            LocalDateTime achievedAt = LocalDateTime.ofEpochSecond((long) (scoreWithTimestamp % 1000L), 0, ZoneOffset.UTC);
            System.out.println("userId: " + entry.getValue() +",排名："+rank+ ", Score: " + score + ", Achieved At: " + achievedAt);
            rank.getAndDecrement();
        });
    }
}

